#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#include <cstring>

#include <functional>
#include <thread>

const int fdnums = 100000;

namespace YZC
{
    // 设置默认端口和最大backlog
    const int defaultPort = 8080;
    const int maxBacklog = 128;

    // 设置回调函数
    using func_t = std::function<int(int)>;

    class tcpServer
    {
    public:
        tcpServer(func_t func, int port = defaultPort)
            : _port(port), _callback(func) {}

        void init()
        {
            // 1.创建socket
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock < 0)
            {
                std::cerr << "sockte err" << std::endl;
                exit(-1);
            }
            std::cout << "socket success" << std::endl;

            // 2 bind绑定fd和端口
            struct sockaddr_in serveraddr;
            memset(&serveraddr, 0, sizeof(serveraddr));
            // 设置地址的信息（协议，ip，端口）
            serveraddr.sin_family = AF_INET;
            serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定任意网卡ip，通常我们访问某一个IP地址是这个服务器的公网网卡IP地址
            serveraddr.sin_port = htons(_port);             // 注意端口16位，2字节需要使用htons。不可
            socklen_t len = sizeof(serveraddr);
            if (bind(_listensock, (struct sockaddr *)&serveraddr, len) < 0)
            {
                std::cerr << "bind err" << std::endl;
                exit(-1);
            }
            std::cout << "bind success" << std::endl;

            // 3 设置sockfd为监听fd
            if (listen(_listensock, maxBacklog) < 0)
            {
                std::cerr << "listen err" << std::endl;
                exit(-1);
            }
            std::cout << "listen success" << std::endl;
        }

        void run()
        {
            // 首先创建pollfd数组
            struct pollfd fds[fdnums] = {0};

            // 注册监视fd到poll关心事件中
            fds[_listensock].fd = _listensock;
            fds[_listensock].events = POLLIN;
            int maxfd = _listensock;
            //
            while (true)
            {
                int n = poll(fds, maxfd + 1, -1);
                if (fds[_listensock].revents & POLLIN)
                {

                    struct sockaddr_in clientaddr;
                    memset(&clientaddr, 0, sizeof(clientaddr));
                    socklen_t len = sizeof(clientaddr);

                    int sockfd = accept(_listensock, (struct sockaddr *)&clientaddr, &len);

                    // 将新的fd增加到rfd中，更新最大fd
                    fds[sockfd].fd = sockfd;
                    fds[sockfd].events = POLLIN;

                    maxfd = sockfd;
                }

                // 注意poll和select一样仍需要遍历所有关心的fd
                for (int i = _listensock + 1; i < maxfd + 1; i++)
                {
                    // 普通读写事件就绪
                    // 处理读事件
                    if (fds[i].revents & POLLIN)
                    {
                        int n = _callback(i);
                        if (n == 0)
                        {
                            // 说明对方关闭，重新处理关心的事件
                            fds[i].fd = -1;
                            fds[i].events = 0;
                            fds[i].revents = 0;
                            close(i);
                        }
                    }
                }
            }
        }

    private:
        int _listensock;
        int _port;
        func_t _callback;
    };

    int serviceIO(int sockfd)
    {
        // 这里仅做简单的数据收发
        char buffer[128] = {0};
        int count = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if (count < 0)
        {
            std::cerr << "recv err" << std::endl;
            exit(-1);
        }
        if (count == 0)
        {
            // 对方关闭
            return 0;
        }
        printf("client --> server:%s\n", buffer);
        send(sockfd, buffer, strlen(buffer), 0);

        return count;
    }

    int serviceHTTP(int sockfd)
    {
        // 这里仅做简单的数据收发

        char buffer[128] = {0};
        int count = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if (count < 0)
        {
            std::cerr << "recv err" << std::endl;
            exit(-1);
        }
        if (count == 0)
        {
            // 对方关闭
            return 0;
        }
        printf("client --> server:%s\n", buffer);

        std::string outbuffer;
        std::string body = "<h1>hello world</h1>";
        outbuffer =
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/html; charset=utf-8\r\n"
            "Content-Length: " +
            std::to_string(body.size()) + "\r\n"
                                          "Server: Apache/2.4.41\r\n"
                                          "Date: Mon, 18 Dec 2023 08:32:10 GMT\r\n"
                                          "X-Frame-Options: DENY\r\n"
                                          "X-Content-Type-Options: nosniff\r\n"
                                          "Referrer-Policy: strict-origin-when-cross-origin\r\n"
                                          "\r\n" // 空行分隔头部和正文
            + body;

        // 无脑向客户端发送一个简单http响应
        send(sockfd, outbuffer.c_str(), outbuffer.size(), 0);
        return count;
    }

}
